package com.hzy.pay.wxpay.service;

import com.github.binarywang.wxpay.bean.order.WxPayAppOrderResult;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.order.WxPayMwebOrderResult;
import com.github.binarywang.wxpay.bean.order.WxPayNativeOrderResult;
import com.github.binarywang.wxpay.bean.request.*;
import com.github.binarywang.wxpay.bean.result.*;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.hzy.pay.wxpay.bean.WeixinpayException;
import com.hzy.pay.wxpay.util.WxpayClientUtil;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

/**
 * 微信支付服务
 * 
 * @author zhuowei.luo
 * @date 2018/7/12
 */
@Slf4j
@Service
public class WeixinpayApiServiceImpl implements WeixinpayApiService {

	private static final Logger logger = LoggerFactory.getLogger(WeixinpayApiServiceImpl.class);
	public WxPayService wxPayService =  WxpayClientUtil.getDefaultWxpayClient();

    /**
     * 作用：统一下单<br>
     * 场景：公共号支付、扫码支付、APP支付
     * Native、JSAPI、APP
     * @return API返回数据
     * @throws Exception
     */
    public  <T> T createOrder(String body, String outTradeNo, String totalFee, String spbillCreateIp, String productId,
                              String openid, String tradeType) throws Exception {
        WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
        orderRequest.setProductId(productId);
        orderRequest.setOpenid(openid);
        orderRequest.setBody(body);
        orderRequest.setOutTradeNo(outTradeNo);
        orderRequest.setTotalFee(BaseWxPayRequest.yuanToFen(String.valueOf(totalFee)));
        orderRequest.setSpbillCreateIp(spbillCreateIp);
        orderRequest.setTradeType(tradeType);
        //放入微信必须获取的参数,如需要其他参数自行set
        try {
            logger.info("weixinpay.createOrder，执行请求！body = {}，outTradeNo={}，totalFee={}，spbillCreateIp={}，productId={}，" +
                    "openid={}", body, outTradeNo, totalFee, spbillCreateIp, productId, openid);
            return wxPayService.createOrder(orderRequest);
        } catch (WxPayException e){
            throw e;
        }
    }

    /**
     * NATIVE 扫码支付
     *
     * 生成ur，url再生成二维码供用户扫码
     *
     * @param body 商家名称-销售商品类目
     * @param outTradeNo 商户系统内部订单号，要求32个字符内，只能是数字、大小写字母_-|* 且在同一个商户号下唯一
     * @param totalFee 订单总金额 单位元
     * @param spbillCreateIp 支持IPV4和IPV6两种格式的IP地址
     * @param productId 商品ID
     * @return
     * @throws Exception
     */
    @Override
    public String createNativeOrder(String body, String outTradeNo, String totalFee, String spbillCreateIp, String productId) throws Exception {
        WxPayNativeOrderResult wxPayNativeOrderResult = createOrder(body, outTradeNo, totalFee, spbillCreateIp, productId,
                null, "NATIVE");
        return wxPayNativeOrderResult.getCodeUrl();
    }

    /**
     * JSAPI 点击支付
     *
     * 调用该方法获取WxPayMpOrderResult参数返回给前台js，js根据参数调用支付方法
     *
     * @param body 商家名称-销售商品类目
     * @param outTradeNo 商户系统内部订单号，要求32个字符内
     * @param totalFee 订单总金额 单位元
     * @param spbillCreateIp 支持IPV4和IPV6两种格式的IP地址
     * @param openid 微信用户的唯一标识，可以通过授权获取用户信息得到
     * @return
     * @throws Exception
     */
    @Override
    public WxPayMpOrderResult createJSAPIOrder(String body, String outTradeNo, String totalFee, String spbillCreateIp, String openid) throws Exception {
        WxPayMpOrderResult wxPayMpOrderResult = createOrder(body, outTradeNo, totalFee, spbillCreateIp, null,
                openid, "JSAPI");
        return wxPayMpOrderResult;
    }

    /**
     * APP 安卓、ios支付
     *
     * 调用该方法获取WxPayAppOrderResult参数返回给安卓、ios
     *
     * @param body 商家名称-销售商品类目
     * @param outTradeNo 商户系统内部订单号，要求32个字符内
     * @param totalFee 订单总金额 单位元
     * @param spbillCreateIp 支持IPV4和IPV6两种格式的IP地址
     * @return
     * @throws Exception
     */
    @Override
    public WxPayAppOrderResult createAPPOrder(String body, String outTradeNo, String totalFee, String spbillCreateIp) throws Exception {
        WxPayAppOrderResult wxPayAppOrderResult = createOrder(body, outTradeNo, totalFee, spbillCreateIp, null,
                null, "APP");
        return wxPayAppOrderResult;
    }

    /**
     * H5 支付
     *
     * 生成ur，url再生成二维码供用户扫码
     *
     * @param body 商家名称-销售商品类目
     * @param outTradeNo 商户系统内部订单号，要求32个字符内
     * @param totalFee 订单总金额 单位元
     * @param spbillCreateIp 支持IPV4和IPV6两种格式的IP地址
     * @return
     * @throws Exception
     */
    @Override
    public String createMWEBOrder(String body, String outTradeNo, String totalFee, String spbillCreateIp) throws Exception {
        WxPayMwebOrderResult wxPayMwebOrderResult = createOrder(body, outTradeNo, totalFee, spbillCreateIp, null,
                null, "MWEB");
        return wxPayMwebOrderResult.getMwebUrl();
    }

	@Override
	public WxPayOrderQueryResult orderQuery(String outTradeNo) throws WeixinpayException {
		try {
            logger.info("weixinpay.orderQuery，执行请求！outTradeNo={}", outTradeNo);
            return wxPayService.queryOrder(WxPayOrderQueryRequest.newBuilder()
                    .outTradeNo(outTradeNo)
                    .build());
		} catch (Exception e) {
			throw new WeixinpayException(e);
		}
	}

	@Override
	public WxPayOrderCloseResult closeOrder(String outTradeNo) throws WeixinpayException {
		try {
            logger.info("weixinpay.closeOrder，执行请求！outTradeNo = {}", outTradeNo);
            return wxPayService.closeOrder(WxPayOrderCloseRequest.newBuilder().outTradeNo(outTradeNo).build());
		} catch (Exception e) {
			throw new WeixinpayException(e);
		}
	}
	
	@Override
	public WxPayRefundResult refund(String outTradeNo, String outRefundNo, String totalFee, String refundFee) throws WeixinpayException {
		try {
            logger.info("weixinpay.refund，执行请求！outTradeNo = {}，outRefundNo={}，totalFee={}，refundFee={}",
                    outTradeNo, outRefundNo, totalFee, refundFee);
            return wxPayService.refund(WxPayRefundRequest.newBuilder()
                    .outTradeNo(outTradeNo)
                    .outRefundNo(outRefundNo)
                    .totalFee(BaseWxPayRequest.yuanToFen(String.valueOf(totalFee)))
                    .refundFee(BaseWxPayRequest.yuanToFen(String.valueOf(refundFee)))
                    .build());
		} catch (Exception e) {
			throw new WeixinpayException(e);
		}
	}
	
	@Override
	public WxPayRefundQueryResult refundQuery(String outTradeNo) throws WeixinpayException {
		try {
            logger.info("weixinpay.refundQuery，执行请求！outTradeNo = {}", outTradeNo);
            return wxPayService.refundQuery(WxPayRefundQueryRequest.newBuilder().outTradeNo(outTradeNo).build());
		} catch (Exception e) {
			throw new WeixinpayException(e);
		}
	}
	
	@Override
	public WxPayBillResult downloadBill(String billDate, String billType) throws WeixinpayException {
		try {
            logger.info("weixinpay.downloadbill，执行请求！billDate = {}，billType={}", billDate, billType);
            return wxPayService.downloadBill(WxPayDownloadBillRequest.newBuilder()
                    .billDate(billDate)
                    .billType(billType)
                    .build());
		} catch (Exception e) {
			throw new WeixinpayException(e);
		}
	}
}
